/* Copyright (c) 2010, David Kreuter. See LICENSE for more information */

#include "headers.h"

map *read_map(uint8 *buf, uint32 len){
	START(read_map);
	uint32 a, A=RL( 0);
	uint32 b, B=RL( 4);
	uint32 c, C=RL( 8);
	uint32 d, D=RL(12);
	uint32 hgss=20+RS(18);
	map *m=malloc(sizeof(map));
	m->len=len;
	m->b=0;

	if(16+A+B+C+D==len)
		a=16;
	else if(hgss+A+B+C+D==len)
		a=hgss;
	else{
		ERROR("Map has wrong length!\n");
		ERROR("%d+%d+%d+%d Wanted: %d DP: %d HGSS: %d\n",
			A,B,C,D,len,16+A+B+C+D,hgss+A+B+C+D);
		hexdump(buf, 640, "Mapheader");
		goto read_map_error;
	}
	b=a+A; c=b+B; d=c+C;

	m->num_collisions=A/2;
	m->collision=malloc(A);
	memcpy(m->collision,buf+a,A);

	m->num_ents=B/0x30;
	if(B%0x30!=0){DEBUG("WTF %8x %8x %8x!\n",B,m->num_ents,m->num_ents*0x30);}

	m->ent=calloc(sizeof(map_ent), m->num_ents);
	for(uint32 i=0;i<m->num_ents;i++){
		map_ent *e=m->ent+i;
		uint32 f=b+0x30*i;
		uint8 *p=buf+f;
		hexdump(p, 30, "Ent");
		e-> b=RL(f);
		e-> x=((float)*(sint32*)(p+0x04))/0x100000;
		e-> y=((float)*(sint32*)(p+0x08))/0x100000;
		e-> z=((float)*(sint32*)(p+0x0C))/0x100000;
		//DEBUG("Thing: %d Position: %f %f %f\n",e->b,e->x,e->y,e->z);
	}

	m->b=read_bmd(buf+c,C);
	m->mat_backup=calloc(sizeof(mdl_mat),m->b->m->num_mats);
	memcpy(m->mat_backup,m->b->m->mat   ,m->b->m->num_mats*sizeof(mdl_mat));

	m->len_d=D;
	m->d=malloc(D);
	memcpy(m->d,buf+d,D);

	END(read_map,m);

	free_map(m);
	return 0;
}

int write_map(map *m, uint8 *buf, uint32 len){
	START(write_map);
	uint32 a= 16,A=RL( 0)=m->num_collisions*2;
	uint32 b=a+A,B=RL( 4)=m->num_ents*0x30;
	uint32 c=b+B,C=RL( 8)=size_bmd(m->b);
	uint32 d=c+C,D=RL(12)=m->len_d;
	   memcpy(     buf+a,m->collision,A);
	write_bmd(m->b,buf+c             ,C);
	   memcpy(     buf+d,m->d        ,D);
	for(uint32 i=0;i<m->num_ents;i++){
		map_ent *e=m->ent+i;
		uint32 f=b+0x30*i;
		uint8 *p=buf+f;
		RS(f)=e->b;
		(*(sint32*)(p+0x04))=(sint32)e-> x*0x100000;
		(*(sint32*)(p+0x08))=(sint32)e-> y*0x100000;
		(*(sint32*)(p+0x0C))=(sint32)e-> z*0x100000;
		//memcpy();
	}
	END(write_map,1);
}

void free_map(map *m){
	START(free_map);
	if(m){
		if(m->collision)free(m->collision);
		if(m->ent)free(m->ent);
		free_bmd(m->b);
		if(m->mat_backup)free(m->mat_backup);
		if(m->d)free(m->d);
		free(m);
	}
	ENDV(free_map);
}

uint32 size_map(map *m){
	START(size_map);
	uint32 len=16+m->num_collisions*2+m->num_ents*0x30+
		size_bmd(m->b)+m->len_d;
	if(len!=m->len){
		DEBUG("WTF! Real: %8x Calculated: %8x\n",len,m->len);
	}
	END(size_map,len);
}

//

void temporary_map_tex_fix(map *mp){
	mdl *m=mp->b->m;
	tex *t=mp->b->t;
	mdl_mat *mb=mp->mat_backup;
	if(!t)return;
	for(uint8 mi=0;mi<m->num_mats;mi++){
		uint8 *ti=&(m->mat[mi].tex_id);
		uint8 *tn=m->tex[mb[mi].tex_id].name;
		uint8 *pi=&(m->mat[mi].pal_id);
		uint8 *pn=m->pal[mb[mi].pal_id].name;
		for(*ti=0;*ti<t->num_texs;(*ti)++)
			if(strcmp(t->tex[*ti].name,tn)==0)break;
		for(*pi=0;*pi<t->num_pals;(*pi)++)
			if(strcmp(t->pal[*pi].name,pn)==0)break;
		if(*ti==t->num_texs)*ti=0;
		if(*pi==t->num_pals)*pi=0;
	}
}
